package ru.niir.goodfil.ui;

import org.apache.commons.lang.StringUtils;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import ru.niir.goodfil.db.Client;
import ru.niir.goodfil.db.ClientGroup;
import ru.niir.goodfil.db.Role;
import ru.niir.goodfil.db.User;
import ru.niir.goodfil.db.dic.DeliveryType;

import javax.faces.model.SelectItem;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Бин для отчета по клиентам
 */
public class ClientsReportBean extends BaseReportsBean {
    /**
     * Колонки шаблона
     */
    private final Map<String, Integer> config = initConfidMap();

    /**
     * Список менеджеров
     */
    private List<SelectItem> managers;

    /**
     * Выбранные поля отчета
     */
    private List<String> selectedClientFields = new ArrayList();

    /**
     * Выбранные менеджеры
     */
    private List<String> selectedManagers = new ArrayList();

    /**
     * {@inheritDoc}
     */
    @Override
    protected String getTemplatedPath() {
        return ".clients.excel.template";
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected String getTemplatedPathDefault() {
        return "C:\\clients_template.xls";
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected String getReportName() {
        return "Отчет по клиентам";
    }

    /**
     * {@inheritDoc}
     */
    @Override
    protected void generateReport(Workbook wb) {
        //  Формируем перечень выбранных полей
        logger.debug("fields: ");
        Set<String> fields = new HashSet<String>();
        for (String field : getSelectedClientFields()) {
            logger.debug("  " + field);
            fields.add(field);
        }

        logger.debug("managers: ");
        Set<Long> managers = new HashSet<Long>();
        if (getSelectedManagers().size() > 0) {
            for (String manager : getSelectedManagers()) {
                Long l = new Long(manager);
                logger.debug("  " + l);
                managers.add(l);
            }
        } else {
            for (SelectItem selectItem : getManagers()) {
                Long l = (Long) selectItem.getValue();
                logger.debug("  " + l);
                managers.add(l);
            }
        }

        //  Получаем всех клиентов и выбираем из них нужных
        logger.debug("Loading clients");
        List<Client> clients = new ArrayList<Client>();
        List<Client> allClients = gf().getClients();
        for (Client client : allClients)
            for (long manager : managers)
                if (client.getManagerId() != null && client.getManagerId() == manager)
                    clients.add(client);
        logger.debug("  loaded: " + clients.size());

        //  Устанавливаем менеджеров
        logger.debug("Loading managers");
        List<User> managersUsers = gf().getUsersByRoleId(Role.MANAGER);
        for (Client client : clients)
            if (client.getManagerId() != null)
                for (User user : managersUsers)
                    if (client.getManagerId() == user.getId())
                        client.setManager(user);

        //  Подгружаем клиентские группы
        Map<Long, ClientGroup> clientgroupsCache = new HashMap<Long, ClientGroup>();
        for (ClientGroup clientGroup : gf().getClientGroups()) {
            clientgroupsCache.put(clientGroup.getId(), clientGroup);
        }

        //  Начинаем формировать отчет
        Sheet sheet1 = wb.getSheetAt(0);
        for (int i = 0; i < clients.size(); i++) {
            Client client = clients.get(i);

            Row row = sheet1.createRow(i + 1);
            for (String columnName : config.keySet()) {
                int columnNum = config.get(columnName);
                String value = "?";

                if (columnName.equals("Наименование компании"))
                    value = client.getCompanyName();
                if (columnName.equals("Юридическое наименование компании"))
                    value = client.getLowName();
                if (columnName.equals("Вид деятельности"))
                    value = client.getCompanyType();
                if (columnName.equals("Специализация"))
                    value = client.getSpeciality();
                if (columnName.equals("Сайт"))
                    value = client.getSite();

                if (columnName.equals("Клиент активен"))
                    value = client.isActive() ? "да" : "нет";
                if (columnName.equals("Контроль суммы закупок"))
                    value = client.isAllowControlSum() ? "да" : "нет";
                if (columnName.equals("Заказы без согласования"))
                    value = client.isAllowQuickOrder() ? "да" : "нет";
                if (columnName.equals("Номер в 1С"))
                    value = client.getC1ClientNum();

                if (columnName.equals("Клиентская группа")) {
                    Set<String> clientGroupsNames = new HashSet<String>();
                    for (Long clientgroupId : client.getClientgroups().values()) {
                        if (clientgroupsCache.containsKey(clientgroupId)) {
                            clientGroupsNames.add(clientgroupsCache.get(clientgroupId).getName());
                        }
                    }
                    value = StringUtils.join(clientGroupsNames.iterator(), ", ");
                }

                if (columnName.equals("Менеджер"))
                    if (client.getManager() != null)
                        value = client.getManager().getFio();

                if (columnName.equals("Адрес фактический"))
                    value = client.getAddressFact();
                if (columnName.equals("Адрес юридический"))
                    value = client.getAddressLaw();
                if (columnName.equals("Адрес доставки"))
                    value = client.getAddressDlv();

                if (columnName.equals("ФИО менеджера"))
                    value = client.getContactFio();
                if (columnName.equals("Рабочий телефон менеджера"))
                    value = client.getContactPhoneWork();
                if (columnName.equals("Мобильный телефон менеджера"))
                    value = client.getContactPhoneMob();
                if (columnName.equals("Email менеджера"))
                    value = client.getContactEmail();

                if (columnName.equals("ФИО руководителя"))
                    value = client.getBossFio();
                if (columnName.equals("Рабочий телефон руководителя"))
                    value = client.getBuhPhoneWork();
                if (columnName.equals("Мобильный телефон руководителя"))
                    value = client.getBossPhoneMob();
                if (columnName.equals("Email руководителя"))
                    value = client.getBossEmail();

                if (columnName.equals("ФИО бухгалтера"))
                    value = client.getBuhFio();
                if (columnName.equals("Рабочий телефон бухгалтера"))
                    value = client.getBuhPhoneWork();
                if (columnName.equals("Мобильный телефон бухгалтера"))
                    value = client.getBuhPhoneMob();
                if (columnName.equals("Email бухгалтера"))
                    value = client.getBuhEmail();

                if (columnName.equals("Комментарий"))
                    value = client.getComment();
                if (columnName.equals("Дата создания"))
                    value = new SimpleDateFormat("dd.MM.yyyy HH:mm").format(client.getCreationDate());

                if (columnName.equals("Величина ТК"))
                    value = String.valueOf(client.getMaxPrice());
                if (columnName.equals("Оговоренная сумма закупок"))
                    value = String.valueOf(client.getMinSum());
                if (columnName.equals("Долг по банку"))
                    value = String.valueOf(client.getDebtBank());
                if (columnName.equals("Долг по кассе"))
                    value = String.valueOf(client.getDebtCash());
                if (columnName.equals("Тип доставки"))
                    value = client.getDeliveryTypeId() == DeliveryType.SELF_DELIVERY ? "Самовывоз" : "Доставка транспортом компании";

                Cell cell = row.createCell(columnNum);
                cell.setCellType(Cell.CELL_TYPE_STRING);
                cell.setCellValue(value);
            }
        }

        //  Теперь удаляем лишние колонки
        for (String columnName : config.keySet()) {
            int columnNum = config.get(columnName);

            boolean found = false;
            for (String field : fields)
                if (columnName.equals(field))
                    found = true;

            if (!found)
                for (int i = 0; i <= clients.size(); i++)
                    sheet1.setColumnWidth(columnNum, 0);
        }
    }

    /**
     * Возвращает перечень доступных полей отчета.
     */
    public List<SelectItem> getClientFields() {
        List<String> strs = new ArrayList<String>();
        for (String key : config.keySet()) strs.add(key);

        //  Сортировка по алфавиту
        Collections.sort(strs);

        List<SelectItem> result = new ArrayList<SelectItem>();
        for (String str : strs) result.add(new SelectItem(str));
        return result;
    }

    /**
     * Возвращает перечень менеджеров систесы.
     */
    public List<SelectItem> getManagers() {
        if (managers == null) {
            if (getSecurityBean().getIsRoleAdministrator()) {
                managers = new ArrayList<SelectItem>();
                List<User> users = gf().getManagers();
                for (User user : users) managers.add(new SelectItem(user.getId(), user.getFio()));
            }

            if (getSecurityBean().getIsRoleManager()) {
                Set<Long> ids = new HashSet<Long>();
                Long currentManagerId = getSecurityBean().getCurrentUser().getId();
                ids.add(currentManagerId);

                ids.addAll(gf().getReplacedManagersByAssistantId(currentManagerId));

                managers = new ArrayList<SelectItem>();
                for (Long managerId : ids) {
                    User user = gf().getUserById(managerId);
                    managers.add(new SelectItem(user.getId(), user.getFio()));
                }
            }

            //  Сортировка по алфавиту
            if (managers != null) {
                Collections.sort(managers, new Comparator<SelectItem>() {
                    public int compare(SelectItem selectItem, SelectItem selectItem1) {
                        return selectItem.getLabel().compareTo(selectItem1.getLabel());
                    }
                });
            }
        }
        return managers;
    }


    /**
     * Инициализация configMap.
     */
    private Map<String, Integer> initConfidMap() {
        Map<String, Integer> config = new HashMap<String, Integer>();
        config.put("Наименование компании", 0);
        config.put("Юридическое наименование компании", 1);
        config.put("Вид деятельности", 2);
        config.put("Специализация", 3);
        config.put("Сайт", 4);

        config.put("Клиент активен", 5);
        config.put("Контроль суммы закупок", 6);
        config.put("Заказы без согласования", 7);
        config.put("Номер в 1С", 8);

        config.put("Клиентская группа", 9);
        config.put("Менеджер", 10);

        config.put("Адрес фактический", 11);
        config.put("Адрес юридический", 12);
        config.put("Адрес доставки", 13);

        config.put("ФИО менеджера", 14);
        config.put("Рабочий телефон менеджера", 15);
        config.put("Мобильный телефон менеджера", 16);
        config.put("Email менеджера", 17);

        config.put("ФИО руководителя", 18);
        config.put("Рабочий телефон руководителя", 19);
        config.put("Мобильный телефон руководителя", 20);
        config.put("Email руководителя", 21);

        config.put("ФИО бухгалтера", 22);
        config.put("Рабочий телефон бухгалтера", 23);
        config.put("Мобильный телефон бухгалтера", 24);
        config.put("Email бухгалтера", 25);

        config.put("Комментарий", 26);
        config.put("Дата создания", 27);

        config.put("Величина ТК", 28);
        config.put("Оговоренная сумма закупок", 29);
        config.put("Долг по банку", 30);
        config.put("Долг по кассе", 31);
        config.put("Тип доставки", 32);
        return config;
    }

    /**
     * Выбранные поля отчета
     */
    public List<String> getSelectedClientFields() {
        return selectedClientFields;
    }

    /**
     * Выбранные поля отчета
     */
    public void setSelectedClientFields(List<String> selectedClientFields) {
        this.selectedClientFields = selectedClientFields;
    }

    /**
     * Выбранные менеджеры
     */
    public void setSelectedManagers(List<String> selectedManagers) {
        this.selectedManagers = selectedManagers;
    }

    /**
     * Выбранные менеджеры
     */
    public List<String> getSelectedManagers() {
        return selectedManagers;
    }
}